#include <CtrlLib/CtrlLib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>

using namespace Upp;
using namespace std;

#include "Dialogs.h"

#include <Sql/sch_schema.h>
#include <Sql/sch_source.h>

#define IMAGECLASS CentroJyPImg
#define IMAGEFILE <CentroJyP/CentroJyP.iml>
#include <Draw/iml_source.h>

// Variables externas
PostgreSQLSession pg_session;
ifstream leerArch;
Array<int> bajasAutomaticas;
Array<int> nroSocios;

/**
 Ventana de bienvenida.
*/
BienvenidaDlg::BienvenidaDlg()
{
	CtrlLayout(*this, "Bienvenido");
	MinimizeBox();
	Icon(CentroJyPImg::icono_min32x32(),CentroJyPImg::icono());
	verListaAfiliados_btn.SetImage(CentroJyPImg::clientes_img__2_());
	verListaAfiliadosAdherentes_btn.SetImage(CentroJyPImg::adherentes());
	verListaPotencialesAfiliados_btn.SetImage(CentroJyPImg::_2clientes_img_2__2_());
	impTxt_btn.SetImage(CentroJyPImg::file_import_icon40x40());
	expAltas_btn.SetImage(CentroJyPImg::file_export_icon40x40());
	expBajas_btn.SetImage(CentroJyPImg::file_export_icon40x40());
	salir_btn.SetImage(CentroJyPImg::salir_icono40x40());
	img.SetImage(CentroJyPImg::SAGRADA_FAMILIA3());
	
	BajasAutomaticasDlg bajas;
	
	verListaAfiliados_btn <<= THISBACK(InitMainWindows);
	verListaAfiliadosAdherentes_btn <<= THISBACK(ListarAfiliadosAdherentes);
	verListaPotencialesAfiliados_btn <<= THISBACK(ListarAfiliadosPotenciales);
	impTxt_btn <<= THISBACK(ImportarArchivo);
	expAltas_btn <<= THISBACK(ExportarAltas);
	expBajas_btn <<= THISBACK(ExportarBajas);
	salir_btn <<= THISBACK(Salir);
	WhenClose = THISBACK(Salir);
}

bool BienvenidaDlg::OpenConnection(String host,String dbname,String user,String pass, String port)
	{
	String cmd =  String().Cat()<<"host="<<host<<" dbname="<<dbname<<" user="<<user<<" password="<<pass << " port="<<port;
	
	if(!pg_session.Open(cmd)) {
		Exclamation(pg_session.GetLastError());
		return false;
	}
	
#ifdef _DEBUG
	pg_session.SetTrace();
#endif
	
	SQL = pg_session;

	//schema
	Progress p;
	p.SetText(t_("Creating _DEBUG database"));
	SqlSchema sch(PGSQL);
	All_Tables(sch);
	if(sch.ScriptChanged(SqlSchema::UPGRADE))
		SqlPerformScript(sch.Upgrade(), p);
	if(sch.ScriptChanged(SqlSchema::ATTRIBUTES)) {
		SqlPerformScript(sch.Attributes(), p);
	}
	if(sch.ScriptChanged(SqlSchema::CONFIG)) {
		SqlPerformScript(sch.ConfigDrop(), p);
		SqlPerformScript(sch.Config(), p);
	}
	sch.SaveNormal();
	
	return true;
}


/**
 Acción del boton ver lista de afialidos.
*/
void BienvenidaDlg::InitMainWindows()
{
	Hide();
	ListadoAfiliadosDlg().Run();
	Show();
}

/**
 Muestra la lista de los potenciales afialiados.
*/
void BienvenidaDlg::ListarAfiliadosPotenciales()
{
	Hide();
	ListadoSolicitudesDlg().Run();
	Show();
}

void BienvenidaDlg::ListarAfiliadosAdherentes()
{
	Hide();
	ListadoAfiliadosAdherentesDlg().Run();
	Show();
}

/**
 Acción del botón Imporat Archivo.
*/
void BienvenidaDlg::ImportarArchivo()
{
	FileSel fs;
	fs.Type("archivos txt (.txt)","*.txt");
	if (!fs.ExecuteOpen("Abrir archivos Alta/Baja"))
		return;
	String nombArchivo = fs;
	String directorio = fs.Get();
	
	leerArchivo(fs);
}

/**
 Lee un archivo en formato .txt.
*/
void BienvenidaDlg::leerArchivo(String archivo)
{
	//char linea[201];
	string linea;
	//Leer primera linea.
//	fscanf(leerArch, "%s", linea);
//	ifstream leerArch;
	leerArch.open(archivo);
//	ifstream leerArch(archivo, ifstream::in);
//	getline(leerArch, linea);
//	leerArch.open(archivo);
	//Chequea si se leyo bien el archivo.	
	if (!leerArch) {
		PromptOK("Error inesperado al leer el archivo!");
   		return;
	}
	int i = 0;
	//Lee primer linea.
//	leerArch.getline(linea, 201);

///	analizarArchivo(linea);
	//Controla fin de archivo.
	
	nroSocios.Clear();
	while (!leerArch.eof()) {
		getline(leerArch, linea);
		if (linea[0] != '\0')
			analizarArchivo(linea);
	}
	compararDatos();
	leerArch.close();
}

void BienvenidaDlg::analizarArchivo(String linea)
{
	Progress progress;
	progress.Title("Leyendo Archivo. Por favor espere!");
	String nro_soc;
	int nro_socio = 0;
	for (int j = 0 ; j <= linea.GetCount() ; j++) {
		progress.Step(1);
		if ((linea[j] >= 48) & (linea[j] <= 57)){
			if ((j > 2) & (j < 9))
				nro_soc << String().Cat() << char(linea[j]);
		}
	}
	nro_socio = atoi(nro_soc);
	nroSocios.Add(nro_socio);
}

/**
 Compara los datos almacenados en la base de datos y los datos contenidos en el archivo .txt.
 Si hay datos que estan en la base de datos y no en el archivo, los mismos son eliminados de
 la base de datos.
*/
void BienvenidaDlg::compararDatos()
{
	bool bandera = false;
	Progress progress;
	progress.Title("Comparando con Base de Datos local. Por favor espere!");
	
	bajasAutomaticas.Clear();
	if (! (SQL * Select(NRO_SOCIO_A).From(AFILIADO))) {
		Exclamation(SQL.GetLastError());
		return;
	}
	while (SQL.Fetch()) {
		bandera = false;
		for (int i = 0 ; i < nroSocios.GetCount() ; i++) {
			progress.Step(1);
			if ((SQL[NRO_SOCIO_A] == nroSocios[i])) {
				bandera = true;
				break;
			}
		}
		if (! bandera)
			bajasAutomaticas.Add(SQL[NRO_SOCIO_A]);
	}
	if (!(bajasAutomaticas.IsEmpty()))
		BajasAutomaticasDlg().Execute();
	else
		PromptOK("¡No hay Bajas de Afiliado registradas para este mes!");
}

/**
 Opción de Exportar Altas desde la ventana inicial.
*/
void BienvenidaDlg::ExportarAltas()
{
	AltasAfiliadosMes listadoAltas;
	listadoAltas.Execute();
}

/**
 Opción de Exportar Bajas desde la ventana inicial.
*/
void BienvenidaDlg::ExportarBajas()
{
	BajaAfiliadoMes listadoBajas;
	listadoBajas.Execute();
}

/**
 Sale de la aplicación.
*/
void BienvenidaDlg::Salir()
{
	//if(PromptYesNo("¿Desea realizar el respaldo de la base de datos antes de salir?")) 
	HacerBackUp();
	if(PromptYesNo("¿Desea salir del programa?")){
		Hide();
		pg_session.Close();
		Close();
	}
}

/**
 Realiza automáticamente el backup de la base de datos.
*/
void BienvenidaDlg::HacerBackUp()
{
	Progress progress;
	progress.Title("Generando Respaldo..");
	
	String out, cmd = String().Cat() << "pg_dump -U postgres -w -f \"" << GetHomeDirectory() << "\\respaldo_centrojyp.backup\"" << " centrojyp";
	if (Sys(cmd, out) == -1) {
		Exclamation("Atención! No se ha podido realizar el respaldo de la base de datos debido al siguiente error:");
		Exclamation(out);
		return;
	}
	
	progress.SetTotal(1500);
	for (int i = 0 ; i < 1500 ; i++)
		progress.SetPos(i);
}

/**
 Reestablece el respaldo de la base de datos.
*/
void BienvenidaDlg::RestaurarBackUp()
{
	FileSel sel;
	sel.Type("Archivo sqlc", "*.sqlc");
	if(! (sel.ExecuteOpen("Elija el archivo de respaldo que desea cargar")))
		return;
	
	back_path = sel.Get();
	//pg_restore -U$username --dbname=$databasename $filename
	String out1, cmd1 = String().Cat() << "psql centrojyp < " << back_path;
	if(Sys(cmd1, out1) == -1) {
		Exclamation(out1);
		return;
	}
	String out, cmd = String().Cat() << "pg_restore -U postgres -C centrojyp" << back_path;
	if (Sys(cmd, out) == -1) {
		Exclamation("Atención! No se ha podido reestablecer el respaldo debido al siguiente error:");
		Exclamation(out);
		return;
	}
	
	PromptOK("La restauración de la base de datos se ha realizado correctamente!");
}